package com.ylr.blog.framework.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylr.user.common.dto.user.UserDto;
import com.ylr.user.framework.resolver.YuUserResolver;
import com.ylr.base.common.constant.Constant;
import com.ylr.base.common.dto.NameValue;
import com.ylr.base.common.dto.PageDto;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.po.user.UserPo;
import com.ylr.base.common.tool.PageQuery;
import com.ylr.base.common.utils.UserUtils;
import com.ylr.base.framework.service.AsyncService;
import com.ylr.base.framework.service.SnowflakeService;
import com.ylr.blog.common.dto.audit_blog.AssignPageEnumDto;
import com.ylr.blog.common.dto.audit_blog.AuditBlogDto;
import com.ylr.blog.common.enums.AuditBlogEnum;
import com.ylr.blog.common.enums.AuditBlogFlowEnum;
import com.ylr.blog.common.enums.BlogEnum;
import com.ylr.blog.common.vo.audit_blog.AssignVo;
import com.ylr.blog.common.vo.audit_blog.AuditBlogFormVo;
import com.ylr.blog.common.vo.audit_blog.AuditVo;
import com.ylr.blog.common.vo.blog.BlogVo;
import com.ylr.blog.framework.entity.AuditBlogEntity;
import com.ylr.blog.framework.entity.AuditBlogFlowEntity;
import com.ylr.blog.framework.entity.BlogEntity;
import com.ylr.blog.framework.mapper.AuditBlogMapper;
import com.ylr.blog.framework.service.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-05-19 20:35:21
 * className: AuditBlogServiceImpl
 * version: 1.0
 * description:
 */
@Service("auditBlogService")
@AllArgsConstructor
public class AuditBlogServiceImpl extends ServiceImpl<AuditBlogMapper, AuditBlogEntity> implements AuditBlogService {

    private static final Logger log = LoggerFactory.getLogger(AuditBlogServiceImpl.class);

    private final SnowflakeService snowflakeService;

    private final BlogService blogService;

    private final BlogTagRelationService blogTagRelationService;

    private final BlogContentService blogContentService;

    private final AuditBlogFlowService auditBlogFlowService;

    private final AsyncService asyncService;

    private final YuUserResolver yuUserResolver;

    @Override
    public Long saveAuditBlog(BlogVo blogVo) {

        AuditBlogEntity auditBlog = this.getNewAuditBlog(blogVo, new Date());
        // 1、插入数据
        baseMapper.insert(auditBlog);
        log.info("保存待审核博客完成");

        return auditBlog.getId();
    }

    @Override
    public Long addAuditBlog(BlogEntity blog) {

        AuditBlogEntity auditBlog = this.getNewAuditBlog(blog, new Date());
        // 1、插入数据
        baseMapper.insert(auditBlog);
        log.info("添加待审核博客完成");

        return auditBlog.getId();
    }

    @Override
    public PageDto<AuditBlogDto> pageAuditBlogList(AuditBlogFormVo auditBlogFormVo) {
        // mp分页对象
        Page<AuditBlogEntity> page = PageQuery.initPage(auditBlogFormVo);

        LambdaQueryWrapper<AuditBlogEntity> auditBlogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        auditBlogLambdaQueryWrapper.select(AuditBlogEntity::getBlogId, AuditBlogEntity::getBlogId, AuditBlogEntity::getAuditUser, AuditBlogEntity::getCode,
                AuditBlogEntity::getTitle, AuditBlogEntity::getType, AuditBlogEntity::getStatus, AuditBlogEntity::getCreateTime);
        // 匹配参数
        auditBlogLambdaQueryWrapper.eq(Objects.nonNull(auditBlogFormVo.getBlogId()), AuditBlogEntity::getBlogId, auditBlogFormVo.getBlogId())
                .eq(Objects.nonNull(auditBlogFormVo.getAuditUser()), AuditBlogEntity::getAuditUser, auditBlogFormVo.getAuditUser())
                .likeRight(StringUtils.isNotBlank(auditBlogFormVo.getCode()), AuditBlogEntity::getCode, auditBlogFormVo.getCode())
                .eq(Objects.nonNull(auditBlogFormVo.getStatus()), AuditBlogEntity::getStatus, auditBlogFormVo.getStatus())
                .eq(AuditBlogEntity::getAuditStatus, AuditBlogEnum.WAIT.getValue())
                .eq(AuditBlogEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 分页查询
        baseMapper.selectPage(page, auditBlogLambdaQueryWrapper);

        List<AuditBlogEntity> auditBlogList = page.getRecords();
        long totalNum = page.getTotal();
        if (auditBlogList.isEmpty()) {
            log.info("待审核博客列表为空");
            return new PageDto<>(Collections.emptyList(), totalNum, auditBlogFormVo.getPageNo(), auditBlogFormVo.getPageSize());
        }
        // 收集分单用户主键
        Set<Long> userIdSet = auditBlogList.stream()
                .map(AuditBlogEntity::getAuditUser)
                .filter(auditUser -> !CommonEnum.DEFAULT_ID.getLongValue().equals(auditUser))
                .collect(Collectors.toSet());
        Map<Long, String> usernameMap = yuUserResolver.getUsernameMap(userIdSet);

        // 数据封装
        List<AuditBlogDto> auditBlogDtoList = new ArrayList<>(auditBlogList.size());
        for (AuditBlogEntity auditBlog : auditBlogList) {
            AuditBlogDto auditBlogDto = new AuditBlogDto();
            auditBlogDto.setId(auditBlog.getId().toString())
                        .setBlogId(auditBlog.getBlogId().toString())
                        .setAuditUser(auditBlog.getAuditUser().toString())
                        .setAuditUserName(usernameMap.get(auditBlog.getAuditUser()))
                        .setCode(auditBlog.getCode())
                        .setTitle(auditBlog.getTitle())
                        .setType(auditBlog.getType())
                        .setTypeName(Optional.ofNullable(auditBlog.getType()).map(BlogEnum::getTypeEnum).map(BlogEnum::getName).orElse(StringUtils.EMPTY))
                        .setStatus(auditBlog.getStatus())
                        .setStatusName(Optional.ofNullable(auditBlog.getStatus()).map(BlogEnum::getStatusEnum).map(BlogEnum::getName).orElse(StringUtils.EMPTY))
                        .setCreateTime(auditBlog.getCreateTime());
            auditBlogDtoList.add(auditBlogDto);
        }
        return new PageDto<>(auditBlogDtoList, totalNum, auditBlogFormVo.getPageNo(), auditBlogFormVo.getPageSize());
    }

    @Override
    public AuditBlogEntity getLastOne(Long blogId) {
        return baseMapper.selectLastOne(blogId, CommonEnum.DELETE_NO.getValue());
    }

    @Override
    public Integer nextVersion(Long blogId) {
        // 获取博客最大的审核版本号
        Integer maxVersion = baseMapper.selectMaxVersion(blogId, CommonEnum.DELETE_NO.getValue());
        if (Objects.isNull(maxVersion)) {
            maxVersion = 0;
        }
        maxVersion += 1;
        return maxVersion;
    }

    @Override
    public AuditBlogEntity getAuditBlog(Long id) {
        // 获取待审核博客
        return this.findAuditBlog(id);
    }

    @Override
    public UserDto getAuditUser(Long id) {
        // 获取待审核博客对象
        AuditBlogEntity auditBlog = this.findAuditBlog(id);
        if (CommonEnum.DEFAULT_ID.getLongValue().equals(auditBlog.getAuditUser())) {
            log.info("待审核博客未被分单");
            return null;
        }
        // 查询 用户模块 获取用户数据
        return yuUserResolver.getUser(auditBlog.getAuditUser());
    }

    @Override
    public AssignPageEnumDto getAssignPageEnum() {
        AssignPageEnumDto assignPageEnumDto = new AssignPageEnumDto();

        // 获取所有待审核博客列表
        LambdaQueryWrapper<AuditBlogEntity> auditBlogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        auditBlogLambdaQueryWrapper.select(AuditBlogEntity::getBlogId, AuditBlogEntity::getTitle, AuditBlogEntity::getAuditUser);
        // 匹配条件
        auditBlogLambdaQueryWrapper.eq(AuditBlogEntity::getAuditStatus, AuditBlogEnum.WAIT.getValue())
                .eq(AuditBlogEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 查询数据
        List<AuditBlogEntity> auditBlogList = baseMapper.selectList(auditBlogLambdaQueryWrapper);

        List<NameValue<String>> auditBlogEnumList = new ArrayList<>();
        Set<Long> userIdSet = new HashSet<>();
        for (AuditBlogEntity auditBlog : auditBlogList) {
            auditBlogEnumList.add(new NameValue<>(auditBlog.getTitle(), auditBlog.getBlogId().toString()));

            if (!CommonEnum.DEFAULT_ID.getLongValue().equals(auditBlog.getAuditUser())) {
                userIdSet.add(auditBlog.getAuditUser());
            }
        }

        List<NameValue<String>> auditUserEnumList = yuUserResolver.getUsernameList(userIdSet);

        BlogEnum[] statusEnums = {
                BlogEnum.SAVE,
                BlogEnum.AUDIT,
                BlogEnum.AUDIT_REJECT,
                BlogEnum. RECHECK_REJECT,
                BlogEnum.EDIT_BLOG,
                BlogEnum.OUT,
                BlogEnum.APPEAL_REJECT,
        };
        List<NameValue<Integer>> statusEnumList = Stream.of(statusEnums)
                .map(statusEnum -> new NameValue<>(statusEnum.getName(), statusEnum.getValue()))
                .collect(Collectors.toList());

        assignPageEnumDto.setAuditBlogEnumList(auditBlogEnumList)
                .setAuditUserEnumList(auditUserEnumList)
                .setStatusEnumList(statusEnumList);
        return assignPageEnumDto;
    }

    @Transactional
    @Override
    public void assignAudit(AssignVo assignVo) {
        // 获取正在进行博客审核分单操作的用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<AuditBlogEntity> auditBlogLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        auditBlogLambdaUpdateWrapper.set(AuditBlogEntity::getAuditUser, assignVo.getAuditUser())
                .set(AuditBlogEntity::getUpdateTime, date)
                .set(AuditBlogEntity::getUpdateUser, userPo.getUsername())
                .set(AuditBlogEntity::getUpdateUserId, userPo.getId());
        // 匹配条件
        auditBlogLambdaUpdateWrapper.eq(AuditBlogEntity::getId, assignVo.getId())
                .eq(AuditBlogEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, auditBlogLambdaUpdateWrapper);
        log.info("待审核博客更新完成。count={}", count);
        if (count == 0) {
            throw new YlrException(ResultEnum.NOT_FOUND);
        }

    }

//    @Transactional
//    @Override
//    public void updateAuditBlog(BlogVo blogVo) {
//        // 获取正在修改待审核博客的用户
//        UserPo userPo = UserUtils.getUser();
//        Date date = new Date();
//
//        // 获取最新一条待审核博客
//        AuditBlogEntity auditBlog = this.getLastOne(blogVo.getId());
//        if (Objects.isNull(auditBlog)) {
//            log.info("待审核博客不存在");
//            throw new YlrException(ResultEnum.NOT_FOUND);
//        }
//        AuditBlogEntity _auditBlog = new AuditBlogEntity();
//        _auditBlog.setId(auditBlog.getId())
//                .setCode(blogVo.getCode())
//                .setTitle(blogVo.getTitle())
//                .setPreface(blogVo.getPreface())
//                .setCoverPicture(blogVo.getCoverPicture())
//                .setType(blogVo.getType())
//                .setStatus(blogVo.getStatus())
//                .setUpdateTime(date)
//                .setUpdateUser(userPo.getUsername())
//                .setUpdateUserId(userPo.getId());
//        // 1、修改数据
//        int count = baseMapper.updateById(auditBlog);
//        log.info("修改待审核博客完成。count={}", count);
//
//        // 2、修改博客正文
//        blogContentService.updateBlogContent(auditBlog.getId(), blogVo.getContent());
//
//        // 3、修改博客关联标签
//        blogTagRelationService.saveBlogTagRelation(auditBlog.getId(), blogVo.getTagIdList());
//    }

    @Override
    public void stopAuditBlog(Long id) {
        // 获取正在终止博客审核的用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        // 1、更新博客
        AuditBlogEntity auditBlog = new AuditBlogEntity();
        auditBlog.setId(id)
                .setAuditStatus(AuditBlogEnum.STOP.getValue())
                .setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getId());
        // 更新数据
        int count = baseMapper.updateById(auditBlog);
        log.info("删除待审核博客完成。count={}", count);
    }

    @Override
    public void commitAudit(AuditVo auditVo) {
        // 获取正在提交博客审核的用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        // 获取待审核博客对象
        AuditBlogEntity auditBlog = findAuditBlog(auditVo.getId());
        if (!userPo.getId().equals(auditBlog.getAuditUser())) {
            log.info("博客已分配给别的用户进行审核。userId={} auditUser={}", userPo.getId(), auditBlog.getAuditUser());
            throw new YlrException(ResultEnum.REFRESH);
        }

        // 更新待审核博客
        auditBlog = new AuditBlogEntity();
        auditBlog.setId(auditVo.getId())
                .setAuditStatus(AuditBlogEnum.FINISH.getValue())
                .setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getId());
        if (auditVo.isAuditReject()) {
            auditBlog.setReply(auditVo.getReply());
        }
        // 更新数据
        int count = baseMapper.updateById(auditBlog);
        log.info("提交博客审核完成。count={}", count);

    }

//    @Transactional
//    @Override
//    public void deleteAuditBlog(Long id) {
//        // 获取正在删除待审核博客的用户
//        UserPo userPo = UserUtils.getUser();
//        Date date = new Date();
//
//        // 1、删除待审核博客
//        AuditBlogEntity auditBlog = new AuditBlogEntity();
//        auditBlog.setId(id)
//                .setDeleteStatus(CommonEnum.DELETE_YES.getValue())
//                .setUpdateTime(date)
//                .setUpdateUser(userPo.getUsername())
//                .setUpdateUserId(userPo.getId());
//        // 更新数据
//        int count = baseMapper.updateById(auditBlog);
//        log.info("删除待审核博客完成。count={}", count);
//
//        asyncService.runAsync(() -> {
//            /*
//                异步操作
//             */
//            // 3、删除待审核博客正文
//            blogContentService.deleteBlogContent(id);
//
//            // 4、删除待审核博客关联的博客标签
//            blogTagRelationService.deleteBlogTagRelation(id);
//        });
//    }

//    @Override
//    public void removeAuditBlog(List<Long> idList) {
//        // 获取正在删除待审核博客的用户
//        UserPo userPo = UserUtils.getUser();
//        Date date = new Date();
//
//        // 1、删除待审核博客
//        LambdaUpdateWrapper<AuditBlogEntity> auditBlogLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
//        // 设置字段值
//        auditBlogLambdaUpdateWrapper.set(AuditBlogEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue())
//                .set(AuditBlogEntity::getUpdateTime, date)
//                .set(AuditBlogEntity::getUpdateUser, userPo.getUsername())
//                .set(AuditBlogEntity::getUpdateUserId, userPo.getId());
//        // 匹配条件
//        auditBlogLambdaUpdateWrapper.in(AuditBlogEntity::getId, idList)
//                .eq(AuditBlogEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
//        // 更新数据
//        int count = baseMapper.update(null, auditBlogLambdaUpdateWrapper);
//        log.info("删除待审核博客完成。count={}", count);
//
//        asyncService.runAsync(() -> {
//            /*
//                异步操作
//             */
//            // 3、删除待审核博客正文
//            blogContentService.removeBlogContent(idList);
//
//            // 4、删除待审核博客关联的博客标签
//            blogTagRelationService.removeBlogTagRelation(idList);
//        });
//    }

    /**
     * 博客参数转化成待审核博客实体对象
     * @param blogVo 博客参数对象
     * @param date   操作日期
     * @return 审核博客实体对象
     */
    private AuditBlogEntity getNewAuditBlog(BlogVo blogVo, Date date) {
        // 获取博客最大的审核版本号
        Integer maxVersion = this.nextVersion(blogVo.getId());

        AuditBlogEntity auditBlog = new AuditBlogEntity();
        auditBlog.setId(snowflakeService.getId())
                .setBlogId(blogVo.getId())
                .setAuditUser(CommonEnum.DEFAULT_ID.getLongValue())
                .setCode(blogVo.getCode())
                .setTitle(blogVo.getTitle())
                .setPreface(blogVo.getPreface())
                .setCoverPicture(blogVo.getCoverPicture())
                .setType(blogVo.getType())
                .setStatus(Optional.ofNullable(blogVo.getStatus()).orElse(Constant.NEGATIVE_ONE))
                .setVersion(maxVersion)
                .setReply(StringUtils.EMPTY)
                .setAuditStatus(AuditBlogEnum.WAIT.getValue())
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.DEFAULT_ID.getLongValue())
                .setCreateTime(date);
        return auditBlog;
    }

    /**
     * 博客对象转化成待审核博客实体对象
     * @param blog 博客参数对象
     * @param date 操作日期
     * @return 审核博客实体对象
     */
    private AuditBlogEntity getNewAuditBlog(BlogEntity blog, Date date) {
        // 获取博客最大的审核版本号
        Integer maxVersion = this.nextVersion(blog.getId());

        AuditBlogEntity auditBlog = new AuditBlogEntity();
        auditBlog.setId(snowflakeService.getId())
                .setBlogId(blog.getId())
                .setAuditUser(CommonEnum.DEFAULT_ID.getLongValue())
                .setCode(blog.getCode())
                .setTitle(blog.getTitle())
                .setPreface(blog.getPreface())
                .setCoverPicture(blog.getCoverPicture())
                .setType(blog.getType())
                .setStatus(blog.getStatus())
                .setVersion(maxVersion)
                .setReply(StringUtils.EMPTY)
                .setAuditStatus(AuditBlogEnum.WAIT.getValue())
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.DEFAULT_ID.getLongValue())
                .setCreateTime(date);
        return auditBlog;
    }

    /**
     * 获取待审核博客
     * @param id 主键
     * @return 待审核博客对象
     */
    private AuditBlogEntity findAuditBlog(Long id) {
        AuditBlogEntity auditBlog = baseMapper.selectById(id);
        if (Objects.isNull(auditBlog)) {
            log.info("待审核博客不存在");
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        if (CommonEnum.DELETE_YES.getValue().equals(auditBlog.getDeleteStatus())) {
            // 待审核博客被删除，判断是否用户撤销审核
            AuditBlogFlowEntity auditBlogFlow = auditBlogFlowService.getLastOne(id);
            if (Objects.isNull(auditBlogFlow)) {
                log.error("博客审核流水不存在，无法判断待审核博客因为什么原因被删除");
                throw new YlrException(ResultEnum.NOT_FOUND);
            }
            if (AuditBlogFlowEnum.WITHDRAW.getValue().equals(auditBlogFlow.getType())) {
                log.info("博客被用户撤销审核");
                throw new YlrException(ResultEnum.REFRESH);
            }
            log.error("博客在审核阶段被删除。type={}", AuditBlogFlowEnum.getTypeEnum(auditBlogFlow.getType()));
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        return auditBlog;
    }


}